package com.excilys.formation.project.entities;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.Index;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;

/**
 * Operation est la classe de lien avec la table operation en base pour l'ORM.
 * 
 * @author excilys
 * 
 */
@Entity
public class Operation {
    /**
     * Identifiant de l'objet.
     */
    private long id;
    /**
     * Montant de l'opération.
     */
    private double montant;

    /**
     * Date de la transaction, par défaut, l'instant présent.
     */
    private DateTime date = DateTime.now();

    /**
     * Date d'effet la transaction, par défaut, l'instant présent.
     */
    private DateTime dateEffet = DateTime.now();

    /**
     * Type de l'opération.
     */
    private TypeOperation typeOperation;

    /**
     * Compte associé à l'opération.
     */
    private Compte compte;

    /**
     * Transaction associée.
     */
    private Transaction transaction;

    /**
     * Constructeur vide.
     */
    public Operation() {

    }

    /**
     * 
     * @param montant
     * @param type
     * @param compte
     * @param transaction
     */
    public Operation(double montant, TypeOperation type, Compte compte, Transaction transaction) {
        this.montant = montant;
        this.typeOperation = type;
        this.compte = compte;
        this.transaction = transaction;
    }

    /**
     * Renvoie l'identifiant de l'opération.
     * 
     * @return l'identifiant de l'opération
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long getId() {
        return id;
    }

    /**
     * Change l'identifiant de l'opération.
     * 
     * @param id
     *            le nouvel identifiant de l'opération.
     */
    public void setId(long id) {
        this.id = id;
    }

    /**
     * Renvoie le montant de l'opération.
     * 
     * @return le montant de l'opération
     */
    @NotNull
    @Index(name = "montant")
    public double getMontant() {
        return montant;
    }

    /**
     * Change le montant de l'opération.
     * 
     * @param montant
     *            le nouveau montant de l'opération.
     */
    public void setMontant(double montant) {
        this.montant = montant;
    }

    /**
     * @return la date de création de la transaction
     */
    @Index(name = "date")
    @NotNull
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    public DateTime getDate() {
        return date;
    }

    /**
     * Modifie la date de création de la transaction.
     * 
     * @param date
     *            la date de création de la transaction.
     */
    public void setDate(DateTime date) {
        this.date = date;
    }

    /**
     * @return la date d'effet de la transaction
     */
    @Index(name = "date_effet")
    @NotNull
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    public DateTime getDateEffet() {
        return dateEffet;
    }

    /**
     * @param dateEffet
     *            la nouvelle date d'effet de la transaction.
     */
    public void setDateEffet(DateTime dateEffet) {
        this.dateEffet = dateEffet;
    }

    /**
     * @return le type de transaction.
     */
    @ManyToOne(optional = false)
    public TypeOperation getTypeOperation() {
        return typeOperation;
    }

    /**
     * @param string
     *            le nouveau le type de transaction.
     */
    public void setTypeOperation(TypeOperation typeoperation) {
        this.typeOperation = typeoperation;

    }

    /**
     * @return Le compte associé à l'opération
     */
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    public Compte getCompte() {
        return compte;
    }

    /**
     * Change le compte de l'opération.
     * 
     * @param compte
     *            Le nouveau compte de l'opération
     */
    public void setCompte(Compte compte) {
        this.compte = compte;
    }

    /**
     * 
     * @return la transaction associée
     */
    @ManyToOne(optional = false)
    public Transaction getTransaction() {
        return transaction;
    }

    /**
     * Change la transaction associée.
     * 
     * @param transaction
     *            la nouvelle transaction associée
     */
    public void setTransaction(Transaction transaction) {
        this.transaction = transaction;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (id ^ (id >>> prime + result));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Operation other = (Operation) obj;
        if (id != other.id) {
            return false;
        }
        return true;
    }

}
